# -*- coding: utf-8 -*-
import time
import requests
from typing import List

from .base_translator import BaseTranslator
from src.config import app_config
from src.utils.translation_cache import TranslationCache

class MicrosoftTranslator(BaseTranslator):
    """
    Performs translation using the Microsoft Translator service.
    """

    def __init__(self, api_key=None, region=None, **kwargs):
        super().__init__()
        self.auth = None
        # Proxy settings can be retrieved from app_config later
        self.proxies = self._set_proxy()
        self.cache = TranslationCache()

    @staticmethod
    def get_name():
        return "Microsoft"

    def _set_proxy(self):
        # Actual proxy logic can be implemented as needed
        pro = app_config.get('proxy')
        if pro:
            return {"https": pro, "http": pro}
        return None

    def translate(self, texts: List[str], source_lang: str, target_lang: str, **kwargs) -> List[str]:
        """
        Translates a list of texts using the Microsoft Translator API, with caching.
        """
        # 1. Check cache for existing translations
        all_translated_texts = [None] * len(texts)
        texts_to_process = []
        model_name = "default" # Microsoft translator doesn't have model selection
        for i, text in enumerate(texts):
            cached_result = self.cache.get(text, self.get_name(), model_name, source_lang, target_lang)
            if cached_result is not None:
                all_translated_texts[i] = cached_result
            else:
                texts_to_process.append({'text': text, 'original_index': i})

        if not texts_to_process:
            return all_translated_texts

        # Prepare for API call
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
        }
        
        if not self.auth:
            self._authenticate(headers)

        tocode = self._map_target_language(target_lang)
        url = self._build_url(source_lang, tocode)
        headers['Authorization'] = f"Bearer {self.auth}"

        # Batch processing for texts that need translation
        batch_size = 50
        texts_for_batching = [item['text'] for item in texts_to_process]
        
        for i in range(0, len(texts_for_batching), batch_size):
            batch_texts = texts_for_batching[i:i + batch_size]
            body = [{'Text': text} for text in batch_texts]
            
            response = requests.post(url, json=body, proxies=self.proxies, headers=headers, verify=False, timeout=300)
            
            if response.status_code != 200:
                error_details = response.text
                raise Exception(f'[Microsoft] status={response.status_code}, details: {error_details}')
            
            re_result = response.json()
            if not re_result:
                raise Exception(f'Empty response from Microsoft API for batch starting at index {i}')
            
            batch_translations = [item['translations'][0]['text'] for item in re_result if 'translations' in item and item['translations']]
            
            if len(batch_translations) != len(batch_texts):
                 raise Exception(f'Mismatch in translation count for batch starting at index {i}. Expected {len(batch_texts)}, got {len(batch_translations)}.')

            # Place translated texts back into the final list and update cache
            for j, translated_text in enumerate(batch_translations):
                original_text = batch_texts[j]
                original_index = texts_to_process[i + j]['original_index']
                all_translated_texts[original_index] = translated_text
                self.cache.set(original_text, translated_text, self.get_name(), model_name, source_lang, target_lang)
            
            time.sleep(0.5)
            
        return all_translated_texts

    def _authenticate(self, headers):
        auth_num = 3
        while auth_num > 0:
            auth_num -= 1
            try:
                auth_response = requests.get('https://edge.microsoft.com/translate/auth', headers=headers, proxies=self.proxies, verify=False)
                if auth_response.status_code != 200:
                    raise Exception(f'[Microsoft]: auth status_code={auth_response.status_code} {auth_response.reason}')
                self.auth = auth_response.text
                return
            except Exception as e:
                if auth_num <= 0:
                    raise Exception(f'Failed to connect to Microsoft Translator: {e}')
                time.sleep(5)
        raise Exception('Failed to get Microsoft Translator authorization')

    def _map_target_language(self, target_lang: str) -> str:
        if target_lang.lower() == 'zh-cn':
            return 'zh-Hans'
        elif target_lang.lower() == 'zh-tw':
            return 'zh-Hant'
        return target_lang

    def _build_url(self, source_lang: str, tocode: str) -> str:
        if source_lang and source_lang.lower() != 'auto':
            return f"https://api-edge.cognitive.microsofttranslator.com/translate?from={source_lang}&to={tocode}&api-version=3.0&includeSentenceLength=true"
        else:
            return f"https://api-edge.cognitive.microsofttranslator.com/translate?to={tocode}&api-version=3.0&includeSentenceLength=true"
